#include <typeinfo>
#include <sstream>

#include "View.h"
#include "DX.h"
#include "Window.h"
#include "DebugLog.h"

View::View( MRect rect ) :	_rect( rect ), 
							_visible( true ), 
							_window( 0 ),
							_canHit( true ),
							_alpha( 0xff ),
							_superView( 0 )
{
	//TRACEFUNC
#ifdef DRAWBORDER
	_border = new Primitive( );

	std::vector< LCVertexPosDiffuse > vec;

	vec.push_back( LCVertexPosDiffuse( -1.0f, -1.0f, 0.0f, D3DCOLOR_ARGB( 0xff, 0xff, 0, 0 ) ) );
	vec.push_back( LCVertexPosDiffuse(  1.0f, -1.0f, 0.0f, D3DCOLOR_ARGB( 0xff, 0xff, 0, 0 ) ) );
	vec.push_back( LCVertexPosDiffuse( -1.0f,  1.0f, 0.0f, D3DCOLOR_ARGB( 0xff, 0xff, 0, 0 ) ) );
	vec.push_back( LCVertexPosDiffuse(  1.0f,  1.0f, 0.0f, D3DCOLOR_ARGB( 0xff, 0xff, 0, 0 ) ) );

	_border->setBuffer( vec );
#endif

}

View::~View()
{
	//if ( window() ) window()->prevHitView = 0;

	//TRACEFUNC
#ifdef DRAWBORDER
	delete _border;
#endif
}

void View::addSubView( View* view )
{
	if ( view )
	{
		_subViews.push_back( view );
		view->setWindow( _window );
		view->setSuperView( this );
	}
}

void View::removeSubView( View* view )
{
	for ( std::vector< View* >::iterator i = _subViews.begin(); i != _subViews.end(); ++i )
	{
		if ( *i == view ) 
		{
			( *i )->setSuperView( 0 );
			( *i )->setWindow( 0 );
			_subViews.erase( i );
			break;
		}
	}

	if ( window() ) window()->prevHitView = 0;
}

unsigned View::countSubViews()
{
	return _subViews.size();
}

View* View::subViewAtIndex( unsigned index )
{
	return _subViews[ index ];
}

void View::removeAllSubViews()
{
	/*for ( size_t i = 0; i < _subViews.size(); ++i )
	{
		delete _subViews[ i ];
	}*/

	_subViews.clear();
}

void View::deleteAllSubViews()
{
	for ( size_t i = 0; i < _subViews.size(); ++i )
	{
		delete _subViews[ i ];
	}

	_subViews.clear();

	if ( window() ) window()->prevHitView = 0;
}

void View::update()
{
	for ( size_t i = 0; i < _subViews.size(); ++i )
	{
		if ( _subViews[ i ]->visible() ) _subViews[ i ]->update();
	}
#ifdef DRAWBORDER
	D3DXMATRIX mTransf;
	D3DXVECTOR2 scale, transl;

	MRect clientRect = window()->getClientRect();
	float kx = 2.0f / clientRect.width();
	float ky = 2.0f / clientRect.height();

	scale.x = ( rect().width() ) / clientRect.width();
	scale.y = ( rect().height() ) / clientRect.height();
	transl.x = ( rect().width() ) / 2.0f * kx - 1.0f + rect().x() * kx;
	transl.y = ( rect().height() ) / 2.0f * ky - 1.0f + rect().y() * ky;
	
	D3DXMatrixTransformation2D( &mTransf, 0, 0, &scale, 0, 0, &transl );
	
	DX::_()->device->SetTransform( D3DTS_WORLD, &mTransf );

	DX::_()->device->SetFVF( LCVertexPosDiffuse::FORMAT );
	DX::_()->device->SetStreamSource( 0, _border->buffer(), 0, sizeof( LCVertexPosDiffuse ) );
	DX::_()->device->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
#endif
}

View* View::superView()
{
	return _superView;
}

void View::setSuperView( View* view )
{
	_superView = view;
}
	
Window* View::window()
{
	return _window;
}

void View::setWindow( Window* window )
{
	for ( std::vector< View* >::iterator i = _subViews.begin(); i != _subViews.end(); ++i )
	{
		( *i )->setWindow( window );
	}
	_window = window;
}

void View::setRect( MRect& rect )
{
	_rect = rect;
}

MRect View::rect()
{
	return _rect;
}

void View::setVisible( bool visible )
{
	_visible = visible;
}

bool View::visible()
{
	return _visible;
}

View* View::hitDistantView( MPoint point )
{
	View* view = 0;
	
	for ( int i = countSubViews() - 1; i >= 0; --i )
	{
		if ( ( view = subViewAtIndex( i )->hitDistantView( point ) ) && view->visible() )
		{
			return view;
		}
	}
	
	view = ( this->rect().isPointInRect( point ) ) ? this : 0;
	
	return view;
}

#ifdef _DEBUG

//void View::dumpView()
//{
//	View* view = this;
//	while ( view = view->superView() ) DEBUGSPACE
//	
//	/*char t[ 50 ];
//	strcpy( t, typeid(view).name() );
//	DEBUGLOG(t)
//	DEBUGPARAM("x", rect().x())
//	DEBUGPARAM("y", rect().y())
//	DEBUGPARAM("w", rect().width())
//	DEBUGPARAM("h", rect().height())
//	DEBUGENDL*/
//
//	DEBUGLOG(description())
//
//	for ( size_t i = 0; i < countSubViews(); ++i )
//	{
//		subViewAtIndex( i )->dumpView();
//	}
//}

//std::wstring View::description()
//{
//	std::wstring ret;
//	std::wostringstream st;
//	st << "View: " << "x = " << rect().x() << " y = " << rect().y() << " w = " << rect().width() << " h = " << rect().height() << std::endl;
//	ret += st.str();
//	return ret;
//}

#ifdef DRAWBORDER
void View::drawBorder()
{
	
}
#endif

#endif
